#include "main_app.h"
#include "json.h"
#include "hifunction.h"
#include "hilog.h"

#define URL_RECORD "/record/record.action"
#define URL_VIDEO_CUT "/record/videoeditor.action"
#define URL_VIDEO_MERGE "/record/videoMerge.action"
#define URL_VIDEO_DURATION "/getTimeLine"

unsigned char FromHex(unsigned char x)   
{   
    unsigned char y;  
    if (x >= 'A' && x <= 'Z') y = x - 'A' + 10;  
    else if (x >= 'a' && x <= 'z') y = x - 'a' + 10;  
    else if (x >= '0' && x <= '9') y = x - '0';  
    else assert(0);  
    return y;  
}  

MainApp::MainApp() 
{
    app_path_ = get_app_path();
    record_manager_ = NULL;
}

MainApp::~MainApp()
{

}

void MainApp::start_app()
{
     //启动web服务
    http_server_ = new CHttpServer("0.0.0.0", 8082, WEB_ROOT_DIR);
    http_server_->start_http(this);

    record_manager_ = new RecordManager;
}

void MainApp::stop_app()
{
    if(record_manager_) {
        delete record_manager_;
        record_manager_ = NULL;
    }
}

string MainApp::on_video_record(string cmd)
{
    hi_trace("%s", cmd.c_str());
    vector<string> vparams = get_param_values(cmd);
    string res = "";    
    int action = atoi(vparams[0].c_str());
    if(1 == action) {
        res = record_manager_->start_record(vparams);             
    }
    else if(2 == action) {
        res = record_manager_->stop_record(vparams);
    }
    else if(3 == action) {
        res = record_manager_->get_record_state(vparams);
    }
    else {
        hi_error("invalid record cmd: %d", action);
    }
           
    return res;       
}   

string MainApp::on_video_cut(string cmd)
{
    int ret = 200;
    string res = "";
    vector<string> vparams = get_param_values(cmd);    
    string oldfile = vparams[0];
    string newfile = vparams[1];
    string starttime = vparams[2];
    string duration = vparams[3];
    
    //检测剪切文件是否存在
    if(is_file_exits(oldfile.c_str())) {
        //创建剪切文件目录    
        string strdir = newfile.substr(0, newfile.find_last_of("/"));
        mkdirs(strdir.c_str());

        stringstream ffmpeg_cmd;
        ffmpeg_cmd<<get_app_path()<<"ffmpeg -ss "<<starttime<<" -i ";
        ffmpeg_cmd<<oldfile<< " -t "<<duration<<" -c copy -copyts -y "<<newfile;

        CutUtil cutobj;
        if(0 != cutobj.start_cut(ffmpeg_cmd.str())) {
            ret = 400;                
        }
    }
    else {
        ret = 400;            
    }

    Json resJson = Json::object({
        {"code", ret},       
        {"msg", "szh"}
    });

    return resJson.toJson(Doc::Indent); 
}

string MainApp::on_video_merge(string cmd)
{
    int ret = 200;
    string res = "";
    vector<string> vparams = get_param_values(cmd); 
    
    int size = vparams.size();
    if(size < 3) {
        ret = 400;
    }             
    else {
        //生成filelist.txt
        string strfilelist = get_app_path() + "filelist.txt";
        ofstream ofresult(strfilelist,ios::out);
        for(int i = 0; i < size-1; i++) {
            ofresult<<"file "<<vparams[i].c_str()<<"\n";                        
        }
        ofresult.close(); 

        //创建合并文件目录
        string mergefile = vparams[size-1];
        string strdir = mergefile.substr(0, mergefile.find_last_of("/"));
        mkdirs(strdir.c_str());

        stringstream ffmpeg_cmd;
        ffmpeg_cmd<<get_app_path()<<"ffmpeg -f concat -i "<<strfilelist;
        ffmpeg_cmd<<" -c copy "<<mergefile;
        MergeUtil merge_obj;
        if(0 != merge_obj.start_merge(ffmpeg_cmd.str()))
        {
            ret = 400;
        }                           
    }  

    Json resJson = Json::object({
        {"code", ret},       
        {"msg", "szh"}
    });
    return resJson.toJson(Doc::Indent); 
}

string MainApp::on_video_duration(string cmd)
{
    int ret = 200;
    string msg = "成功";
    string alltime = "";
    vector<string> vparams = get_param_values(cmd); 
    string playUrl = vparams[0];

    if(get_video_duration(playUrl, alltime) != 0){
        ret = 400;
        msg = "失败";
    }

     Json resJson = Json::object({
        {"data", alltime.c_str()},       
        {"msg", msg.c_str()}
    });
    return resJson.toJson(Doc::Indent); 
}

int MainApp::get_video_duration(string filename, string& alltime)
{//00:00:00 小时：分钟：秒
    stringstream cmd;
    cmd<<get_app_path()<<"ffmpeg -i "<<filename;    
    char result[1024] = {0};
    int rescmd = proc_shell_cmd((char*)cmd.str().c_str(), result); 
    if(rescmd < 0) {
        return -1;               
    }
    else {       
           
        string str(result);     
        size_t pos =  str.find("Duration:");
        if(pos == string::npos) {
            hi_error("result: %s", result); 
            return -1;
        }
        else {
            size_t dst_pos = str.find('.', pos);
            alltime = str.substr(pos+9, 8);
            //hi_trace("alltime: %s", alltime.c_str());            
        }                  
    }    

    return 0;         
}

string MainApp::on_video_add_subtitle(string cmd)
{
    string res = "";
    return res;
}
    
void MainApp::proc_http_msg(CHttpReq *req)
{
    if(req == NULL) return;
    
    string res = "";
    string action = req->get_http_action();
    string params = req->get_http_params();
    
    //hi_trace("--------action: %s params: %s", action.c_str(), params.c_str());    
    string dparams = urldecode(params);
    hi_trace("---------urldecode params: %s", dparams.c_str());
  
    if(req->req_http_html()) return;
    
    if(action.compare(URL_RECORD) == 0) {                
        res = on_video_record(dparams);        
    }
    else if(action.compare(URL_VIDEO_MERGE) == 0) {
        res = on_video_merge(dparams);
    }
    else if(action.compare(URL_VIDEO_CUT) == 0) {
        res = on_video_cut(dparams);
    }
    else if(action.compare(URL_VIDEO_DURATION) == 0) {
        res = on_video_duration(dparams);        
    }
   // hi_trace("http res: %s", res.c_str());
    req->response_info(res);
}

vector<string> MainApp::get_param_values(string cmd)
{//demo: http://192.168.1.137:8080/recordAction?action=1&beginTime=2654845748
 //       &encryptCode=sldfs&uniqueCode=1394343&user=test&msg=null&path=null&callbackurl=null&otherParam=null
    std::vector<std::string> resVec;
    if ("" == cmd)
    {
        return resVec;
    }
    //方便截取最后一段数据
    
    string pattern = "&";
    std::string strs = cmd + pattern;
    size_t pos = strs.find(pattern);
    size_t size = strs.size();

    while (pos != std::string::npos)
    {
        std::string x = strs.substr(0,pos);
        resVec.push_back(x);
        strs = strs.substr(pos+1,size);
        pos = strs.find(pattern);
    }

    vector<string> values;
    values.clear();

    for(int i = 0; i < resVec.size(); i++) {
        string key_value = resVec[i];
        string str_split = "=";       
        size_t pos = key_value.find(str_split);
        size_t size = key_value.size();
        key_value = key_value.substr(pos+1,size-pos-1);
        values.push_back(key_value);
        cout<<"params: "<<key_value<<endl;       
    }
    return values;
}

string MainApp::urldecode(const std::string& str)  
{  
    std::string strTemp = "";  
    size_t length = str.length();  
    for (size_t i = 0; i < length; i++)  
    {  
        if (str[i] == '+') strTemp += ' ';  
        else if (str[i] == '%')  
        {  
            assert(i + 2 < length);  
            unsigned char high = FromHex((unsigned char)str[++i]);  
            unsigned char low = FromHex((unsigned char)str[++i]);  
            strTemp += high*16 + low;  
        }  
        else strTemp += str[i];  
    }  
    return strTemp;  
}  

